package com.yunyao.framework.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunyao.common.constant.DictConstants;
import com.yunyao.common.constant.enums.AuditStatusEnums;
import com.yunyao.common.constant.enums.DataDeletedStatus;
import com.yunyao.common.constant.enums.DateFormatPattern;
import com.yunyao.common.core.BaseContext;
import com.yunyao.common.dto.payment.PaymentDto;
import com.yunyao.common.utils.DictCacheUtils;
import com.yunyao.common.utils.ReflectUtil;
import com.yunyao.common.web.enums.ResultMsgEnum;
import com.yunyao.common.web.util.ConvertUtil;
import com.yunyao.common.web.util.PageResult;
import com.yunyao.common.web.util.StringUtils;
import com.yunyao.common.web.util.YResult;
import com.yunyao.dao.model.*;
import com.yunyao.dao.service.bamu.*;
import com.yunyao.dao.service.system.IUserService;
import com.yunyao.framework.audit.ReceiveAuditHandle;
import com.yunyao.framework.dto.audit.ApprovalDto;
import com.yunyao.framework.dto.audit.SubmitApprovalDto;
import com.yunyao.framework.dto.payment.ReceiveNodeSaveDto;
import com.yunyao.framework.dto.payment.ReceiveSaveDto;
import com.yunyao.framework.service.ReceivePaymentService;
import com.yunyao.framework.vo.pay.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 收款管理ServiceImpl
 *
 * @author chenyejian
 * @Date 2024/7/31 11:24
 */
@Service
@Slf4j
public class ReceivePaymentServiceImpl implements ReceivePaymentService {
    @Autowired
    private IBamuReceiveService receiveService;
    @Autowired
    private IBamuReceiveHistoryService receiveHistoryService;
    @Autowired
    private IBamuReceiveContractInvoiceService receiveContractInvoiceService;
    @Autowired
    private IBamuReceiveHistoryInvoiceService receiveHistoryInvoiceService;
    @Autowired
    private IBamuReceiveNodeService receiveNodeService;
    @Autowired
    private ReceiveAuditHandle auditHandle;

    @Autowired
    private IBamuSaleContractService saleContractService;

    @Autowired
    private IUserService userService;

    @Override
    public YResult<PageResult<ReceivePaymentVO>> pageList(PaymentDto paymentDto) {
        // 构建查询条件
        LambdaQueryWrapper<BamuReceive> wrapper = new LambdaQueryWrapper<BamuReceive>()
                .like(StringUtils.isNotEmpty(paymentDto.getContractName()), BamuReceive::getContractName, paymentDto.getContractName())
                .like(StringUtils.isNotEmpty(paymentDto.getProjectName()), BamuReceive::getProjectName, paymentDto.getProjectName())
                .like(StringUtils.isNotEmpty(paymentDto.getPurchaseDeptName()), BamuReceive::getPurchaseDeptName, paymentDto.getPurchaseDeptName())
                .eq(BamuReceive::getIsDeleted, DataDeletedStatus.NO.getType())
                .orderByDesc(BamuReceive::getCreatedAt)
                .in(CollectionUtils.isNotEmpty(BaseContext.getProjectList()), BamuReceive::getProjectId, BaseContext.getProjectList())
                .in(CollectionUtils.isNotEmpty(BaseContext.getSupplierList()), BamuReceive::getSupplierDeptId, BaseContext.getSupplierList());
        if (StringUtils.isNotEmpty(paymentDto.getBeginDate())) {
            wrapper.ge(BamuReceive::getReceiveDate, ConvertUtil.getString2Date(paymentDto.getBeginDate(), DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        }
        if (StringUtils.isNotEmpty(paymentDto.getEndDate())) {
            wrapper.le(BamuReceive::getReceiveDate, ConvertUtil.getString2Date(paymentDto.getEndDate(), DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        }
        // 分页查询
        IPage<BamuReceive> payPage = new Page<>(paymentDto.getPageIndex(), paymentDto.getPageSize());
        payPage = receiveService.page(payPage, wrapper);

        // 处理查询结果
        if (CollectionUtils.isEmpty(payPage.getRecords())) {
            return YResult.success(new PageResult<>());
        }



        // 转换为VO对象列表
        List<ReceivePaymentVO> list = daoToVoList(payPage.getRecords());

        // 返回分页结果
        return YResult.success(new PageResult<>(list, payPage.getCurrent(), payPage.getSize(), payPage.getPages(), payPage.getTotal()));
    }

    @Override
    public YResult<ReceivePaymentVO> getDetailById(String id) {
        return YResult.success(daoToVo(receiveService.getById(id)));
    }

    @Override
    public YResult<String> deleteById(String id) {
        if (StringUtils.isNotEmpty(id)) {
            BamuReceive receive = receiveService.getById(id);
            if (receive == null) {
                return YResult.error(ResultMsgEnum.NO_DATA);
            }
            receive.setIsDeleted(DataDeletedStatus.YES.getType());
            receiveService.saveOrUpdate(receive);
            return YResult.success("删除成功");
        }
        return YResult.error(ResultMsgEnum.ERROR);
    }

    /**
     * 根据合同id查询历史列表
     * @param paymentDto
     * @return
     */
    @Override
    public YResult<List<ReceiveHistoryVO>> getHistoryList(PaymentDto paymentDto) {
        // 构建查询条件
        LambdaQueryWrapper<BamuReceiveHistory> wrapper = new LambdaQueryWrapper<BamuReceiveHistory>()
                .eq(StringUtils.isNotEmpty(paymentDto.getContractId()),BamuReceiveHistory::getContractId, paymentDto.getContractId())
                .eq(StringUtils.isNotEmpty(paymentDto.getReceiveId()),BamuReceiveHistory::getReceiveId, paymentDto.getReceiveId())
                .eq(BamuReceiveHistory::getIsDeleted, DataDeletedStatus.NO.getType())
                .orderByDesc(BamuReceiveHistory::getCreatedAt);
        List<ReceiveHistoryVO> list = receiptHistoryDaoToVoList(receiveHistoryService.list(wrapper));
        if(CollectionUtils.isNotEmpty(list)){
            list.forEach(ReflectUtil::padding);
        }
        /**
         * 添加总和列
         */
        /*if (CollectionUtils.isNotEmpty(list)) {
            BigDecimal  total = list.stream().map(ReceiveHistoryVO::getReceivePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            ReceiveHistoryVO totalVo = new ReceiveHistoryVO();
            totalVo.setReceivePrice(total);
            totalVo.setReceiveDate("合计");
            list.add(totalVo);
        }*/
        return YResult.success(list);
    }


    @Override
    public YResult<List<ReceiveContractInvoiceVO>> getNowInvoiceList(String contractId) {
        List<BamuReceiveContractInvoice> invoiceList = receiveContractInvoiceService.getReceiveContractInvoiceByContractId(contractId);
        return YResult.success(invoiceDaoToVoList(invoiceList));
    }

    /**
     * 收款发票列表
     * @param paymentDto
     * @return
     */
    @Override
    public YResult<List<ReceiveContractInvoiceVO>> getReceiveInvoiceList(PaymentDto paymentDto) {
        // 构建查询条件
        LambdaQueryWrapper<BamuReceiveContractInvoice> wrapper = new LambdaQueryWrapper<BamuReceiveContractInvoice>()
                .eq(BamuReceiveContractInvoice::getReceiveId, paymentDto.getReceiveId())
                .eq(BamuReceiveContractInvoice::getIsDeleted, DataDeletedStatus.NO.getType());
        return YResult.success(invoiceDaoToVoList(receiveContractInvoiceService.list(wrapper)));
    }

    /**
     * 收款节点
     * @param paymentDto
     * @return
     */
    @Override
    public YResult<List<ReceiveNodeVO>> getReceiveNodeList(PaymentDto paymentDto) {
        // 构建查询条件
        LambdaQueryWrapper<BamuReceiveNode> wrapper = new LambdaQueryWrapper<BamuReceiveNode>()
                .eq(BamuReceiveNode::getReceiveId, paymentDto.getId())
                .eq(BamuReceiveNode::getIsDeleted, DataDeletedStatus.NO.getType());
        return YResult.success(nodeDaoToVoList(receiveNodeService.list(wrapper)));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public YResult<String> saveOrUpdate(ReceiveSaveDto dto) {
        if (dto != null) {
            Boolean isEdit = false;
            BamuReceive receive = new BamuReceive();
            //编辑
            if (StringUtils.isNotEmpty(dto.getId())) {
                receive = receiveService.getById(dto.getId());
                if (receive == null) {
                    return YResult.error("传入的收款id不存在数据");
                }
                isEdit = true;
            }
            BamuSaleContract saleContract = saleContractService.getById(dto.getContractId());
            if (saleContract != null) {
                copySaleContract2Receive(saleContract, receive);
            }
            receive.setReceiveDate(dto.getReceiveDate());
            receive.setReceivePrice(dto.getReceivePrice());
            receive.setReceiveType(dto.getReceiveType());
            if (dto.getReceiveNodeId() != null && dto.getReceiveNodeId().size()>0) {
                receive.setReceiveNodeId(dto.getReceiveNodeId().stream().map(String::valueOf).collect(Collectors.joining(",")));
            }
            try {
                receive.setReceiveTypeName(DictCacheUtils.getDictValue(DictConstants.COLLECTION_METHODS,dto.getReceiveType()));
            }catch (Exception e){
                log.error("收款类型字典数据异常",e);
            }
            receive.setFile(JSON.toJSONString(dto.getFile()));
            receive.setMark(dto.getMark());
            receive.setStatus(0);
            receive.setIsDeleted(DataDeletedStatus.NO.getType());
            receiveService.saveOrUpdate(receive);

            /**
             * 新增保存
             */
            if (!isEdit) {
                String contractId = receive.getContractId();
                List<BamuReceiveContractInvoice> receiveContractInvoiceList = receiveContractInvoiceService.getReceiveContractInvoiceByContractId(contractId);
                BigDecimal receivePrice = receive.getReceivePrice();
                if (CollectionUtils.isNotEmpty(receiveContractInvoiceList)) {
                    for (BamuReceiveContractInvoice receiveContractInvoice : receiveContractInvoiceList){
                        receiveContractInvoice.setContractId(contractId);
                        receiveContractInvoice.setReceiveId(receive.getId());
                        receiveContractInvoice.setAuditStatus(ConvertUtil.null2String(AuditStatusEnums.SUBMITTED.getType()));
                        receiveContractInvoice.setIsDeleted(DataDeletedStatus.NO.getType());
                        receiveContractInvoice.setStatus(0);
                        /**
                         * 收款金额>发票金额，则更新为剩余金额
                         */
                        if(receiveContractInvoice.getInvoicePrice()!=null){
                            if (receivePrice.compareTo(receiveContractInvoice.getInvoicePrice()) >= 0) {
                                receiveContractInvoice.setPrePrice(receiveContractInvoice.getInvoicePrice());
                                receiveContractInvoice.setReceivePrice(receiveContractInvoice.getInvoicePrice());
                                receiveContractInvoice.setNoReceivePrice(BigDecimal.ZERO);
                                /**
                                 * receivePrice-invoicePrice=剩余金额
                                 */
                                receivePrice = receivePrice.subtract(receiveContractInvoice.getInvoicePrice());
                            }else {
                                /**
                                 * receivePrice<invoicePrice，则更新为收款金额
                                 */
                                receiveContractInvoice.setPrePrice(receivePrice);
                                receiveContractInvoice.setReceivePrice(receivePrice);
                                receiveContractInvoice.setNoReceivePrice(receiveContractInvoice.getInvoicePrice().subtract(receivePrice));
                            }
                            receiveContractInvoice.setPrePrice(receive.getReceivePrice());
                        }
                    }
                    receiveContractInvoiceService.saveBatch(receiveContractInvoiceList);
                }
            }




            String receiveId = receive.getId();
                List<ReceiveNodeSaveDto> receiveNodes = dto.getReceiveNodes();
                if (CollectionUtils.isNotEmpty(receiveNodes)) {
                    receiveNodes.forEach(nodeSaveDto -> {
                        nodeSaveDto.setReceiveId(receiveId);
                        nodeSaveOrUpdate(nodeSaveDto);
                    });
                }
            return YResult.success(receive.getId());
        }
        return YResult.error(ResultMsgEnum.PARAM_ERROR);
    }

    /**
     * 复制销售合同信息到收款信息
     * @param saleContract
     * @param receive
     */
    private void copySaleContract2Receive(BamuSaleContract saleContract, BamuReceive receive) {
        //获取销售合同
        receive.setContractId(saleContract.getId());
        receive.setContractNo(saleContract.getContractNo());
        receive.setContractName(saleContract.getContractName());
        receive.setProjectId(saleContract.getProjectId());
        receive.setProjectName(saleContract.getProjectName());
        receive.setSignDate(saleContract.getSignDate());
        receive.setContractMethod(saleContract.getContractMethod());
        receive.setContractTotalPrice(saleContract.getContractTotalPrice());
        receive.setPurchaseDeptId(saleContract.getPurchaseDeptId());
        receive.setPurchaseDeptName(saleContract.getPurchaseDeptName());
        receive.setProjectDeptId(saleContract.getProjectDeptId());
        receive.setProjectDeptName(saleContract.getProjectDeptName());
        receive.setContractEndDate(saleContract.getPaymentDeadlineDate());
        receive.setSupplierDeptId(saleContract.getSupplierDeptId());
        receive.setSupplierDeptName(saleContract.getSupplierDeptName());
    }

    @Override
    public YResult<String> nodeSaveOrUpdate(ReceiveNodeSaveDto dto) {
        // 检查传入的对象是否为空
        if (Objects.isNull(dto)) {
            log.error("ReceiveNodeSaveDto is null.");
            return YResult.error(ResultMsgEnum.PARAM_ERROR);
        }
        try {
            BamuReceiveNode receiveNode = getBamuReceiveNode(dto);
            // 执行保存或更新操作，并检查是否成功
            boolean saveOrUpdate = receiveNodeService.saveOrUpdate(receiveNode);
            if (!saveOrUpdate) {
                log.error("Failed to save or update payment.");
                return YResult.error(ResultMsgEnum.SYS_ERROR);
            }
            // 操作成功，返回支付ID
            return YResult.success(dto.getId());
        } catch (Exception e) {
            log.error("Unexpected error occurred: {}", e.getMessage(), e);
            return YResult.error(ResultMsgEnum.SYS_ERROR);
        }
    }

    private BamuReceiveNode getBamuReceiveNode(ReceiveNodeSaveDto dto) {
        BamuReceiveNode receiveNode = new BamuReceiveNode();
        receiveNode.setId(dto.getId());
        receiveNode.setNodeId(dto.getNodeId());
        receiveNode.setNodeName(dto.getNodeName());
        receiveNode.setReceivePrice(dto.getReceivePrice());
        receiveNode.setContractId(dto.getContractId());
        receiveNode.setReceiveId(dto.getReceiveId());
        receiveNode.setNodeType(dto.getNodeType());
        receiveNode.setNodeTriggerType(dto.getNodeTriggerType());
        receiveNode.setBackPaymentDate(dto.getBackPaymentDate());
        receiveNode.setReceiveDate(dto.getReceiveDate());
        return receiveNode;
    }

    @Override
    public YResult<String> invoiceConnect(PaymentDto paymentDto) {
        return null;
    }

    /**
     * 提交审批操作
     * 该方法接收一个审批数据传输对象（SaleContractSubmitApprovalDto），尝试提交销售合同的审批流程
     * 如果提交成功，返回一个成功结果，包含审批的ID；如果提交过程中发生异常，
     * 则返回一个错误结果，包含异常信息
     *
     * @param approvalDto 审批数据传输对象，包含审批所需的必要信息
     * @return YResult<String> 返回一个包含结果状态和审批ID的结果对象
     */
    @Override
    public YResult<String> submitApproval(SubmitApprovalDto approvalDto) {
        try {
            // 调用处理类的submit方法，传入审批ID，执行审批提交操作
            auditHandle.submit(approvalDto.getId());
            // 如果审批提交成功，返回成功结果，包含审批的ID
            return YResult.success(approvalDto.getId());
        } catch (Exception e) {
            // 如果审批提交过程中发生异常，返回错误结果，包含异常信息
            return YResult.error(e.getMessage());
        }
    }

    /**
     * 审批销售合同
     * 该方法接收一个销售合同审批数据传输对象，并尝试对其进行审批操作
     * 如果审批成功，返回一个表示成功的YResult对象，包含审批后的ID
     * 如果审批过程中出现异常，返回一个表示错误的YResult对象，包含错误信息
     *
     * @param approvalDto 销售合同审批Dto，包含审批所需信息
     * @return YResult对象，表示审批结果
     */
    @Override
    public YResult<String> approval(ApprovalDto approvalDto) {
        try {
            // 调用审批处理类的approval方法进行审批操作
            auditHandle.approval(approvalDto);
            // 审批成功后，返回成功结果，携带审批后的ID
            return YResult.success(approvalDto.getId());
        } catch (Exception e) {
            // 审批过程中发生异常，返回错误结果，携带异常信息
            return YResult.error(e.getMessage());
        }
    }

    @Override
    public YResult<String> revocation(ApprovalDto approvalDto) {
        return null;
    }

    @Override
    public YResult<ReceiveStatisticalPriceVO> getStatisticalPrice(PaymentDto paymentDto) {
        ReceiveStatisticalPriceVO vo = new ReceiveStatisticalPriceVO();
        List<BamuReceiveContractInvoice> invoiceList = receiveContractInvoiceService.getReceiveContractInvoiceByContractId(paymentDto.getContractId());
        BigDecimal unReceivePrice = new BigDecimal(0);
        BigDecimal overduePrice = new BigDecimal(0);
        if (CollectionUtils.isNotEmpty(invoiceList)) {
            for (BamuReceiveContractInvoice invoice : invoiceList) {
                if (null!=invoice.getNoReceivePrice()) {
                    unReceivePrice = unReceivePrice.add(invoice.getNoReceivePrice());
                }
                /**
                 * 逾期未收款
                 */
//                if (invoice.getInvoiceDate().before(new Date())) {
//                    if (null != invoice.getInvoicePrice()) {
//                        overduePrice = overduePrice.add(invoice.getOverduePrice());
//                    }
//                }
            }
        }
            vo.setUnReceivePrice(unReceivePrice);
            vo.setOverduePrice(overduePrice);
        return YResult.success(vo);
    }

    /**
     * 收款对象list转化vo
     * @param list
     * @return
     */
    private List<ReceivePaymentVO> daoToVoList(List<BamuReceive> list) {
        // 转换
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().map(dao -> daoToVo(dao)).collect(Collectors.toList());
        }
        return null;
    }
    private ReceivePaymentVO daoToVo(BamuReceive dao){
        ReceivePaymentVO vo = new ReceivePaymentVO();
        BeanUtils.copyProperties(dao,vo);
        vo.setReceiveDate(ConvertUtil.getFormatDate(dao.getReceiveDate(), false, DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        vo.setCreatedAt(ConvertUtil.getFormatDate(dao.getCreatedAt(), false, DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        vo.setSignDate(ConvertUtil.getFormatDate(dao.getSignDate(), false, DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        vo.setCreatedBy(userService.getRealNameByUserId(dao.getCreatedBy()));
        if (ConvertUtil.getIntValue(dao.getContractPrePaymentStatus(),0)==0 && ConvertUtil.getIntValue(dao.getOrderPrePaymentStatus(),0)==0){
            vo.setReceiveItem("实付款");
        }else{
            vo.setReceiveItem("预付款");
        }
        /**
         * 收款方式字典转化
         */
        vo.setReceiveTypeName(DictCacheUtils.getDictValue("collection_methods", dao.getReceiveType()));
        return vo;
    }


    /**
     * 收款发票对象lis转化vo
     */
    private List<ReceiveContractInvoiceVO> invoiceDaoToVoList(List<BamuReceiveContractInvoice> list) {
        // 转换
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().map(dao -> invoiceDaoToVo(dao)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }
    private ReceiveContractInvoiceVO invoiceDaoToVo(BamuReceiveContractInvoice dao) {
        ReceiveContractInvoiceVO vo = new ReceiveContractInvoiceVO();
        BeanUtils.copyProperties(dao, vo);
        return vo;
    }

    /**
     * 收款节点对象list转化vo
     */
    private List<ReceiveNodeVO> nodeDaoToVoList(List<BamuReceiveNode> list) {
        // 转换
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().map(dao -> nodeDaoToVo(dao)).collect(Collectors.toList());
        }
        return null;
    }
    private ReceiveNodeVO nodeDaoToVo(BamuReceiveNode dao) {
        ReceiveNodeVO vo = new ReceiveNodeVO();
        BeanUtils.copyProperties(dao, vo);
        return vo;
    }


    /**
     * 收款历史记录对象list转化vo
     */
    private List<ReceiveHistoryVO> receiptHistoryDaoToVoList(List<BamuReceiveHistory> list) {
        // 转换
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().map(dao -> receiptHistoryDaoToVo(dao)).collect(Collectors.toList());
        }
        return null;
    }
    private ReceiveHistoryVO receiptHistoryDaoToVo(BamuReceiveHistory dao) {
        ReceiveHistoryVO vo = new ReceiveHistoryVO();
        BeanUtils.copyProperties(dao, vo);
        vo.setReceiveDate(ConvertUtil.getFormatDate(dao.getReceiveDate(), false,DateFormatPattern.YEAR_MONTH_DAY.getPattern()));
        return vo;
    }

}
